/*
 * Author: yezi
 * E-mail: okye328@gmail.com
 * Create time: Dec 31, 2012 10:46:54 PM
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 *
 */
package com.kanbox.linux.fs;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.LinkedList;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.alibaba.fastjson.JSONArray;
import com.kanbox.linux.GlobalConf;
import com.kanbox.linux.operation.FileList;
import com.kanbox.linux.util.ByteUtil;

public class FolderHash {

	private static Logger logger = LoggerFactory.getLogger(FolderHash.class);

	static {
		File hashFolder = new File(GlobalConf.HASH_FOLDER);
		if (hashFolder.exists() && !hashFolder.isDirectory()) {
			hashFolder.delete();
		}
		hashFolder.mkdirs();
	}

	private static final String LINE_SEPARATOR = System
			.getProperty("line.separator");

	private String fileName;// Compute for path with sha-1
	private String path;
	private String hash;
	private String contents;

	private File file;

	/**
	 * 
	 * @param path
	 * @param hash
	 * @param contents
	 *            a JSONArray
	 */
	public FolderHash(String path, String hash, String contents) {
		this.path = path;
		this.hash = hash;
		this.contents = contents;
		fileName = getFileName();
		try {
			write();
		} catch (IOException e) {
			logger.error("Error when saving file", e);
		}
	}

	public FolderHash(String path) {
		this.path = path;
		this.hash = "";
		fileName = getFileName();
		try {
			read();
		} catch (IOException e) {
			logger.error("Get child nodes error", e);
		}
	}

	public FolderHash(File file) {
		this.file = file;
		fileName = file.getName();
		try {
			read();
		} catch (IOException e) {
			logger.error("Get child nodes error", e);
		}
	}

	private String getFileName() {
		MessageDigest messageDigest = null;
		try {
			messageDigest = MessageDigest.getInstance("SHA-1");
		} catch (NoSuchAlgorithmException e) {
			// Will not happen.
		}
		messageDigest.reset();
		messageDigest.update(this.path.getBytes());
		byte[] bs = messageDigest.digest();
		fileName = ByteUtil.bytesToString(bs);
		return fileName;
	}

	public List<INode> getChildNodes() {
		List<INode> res = new LinkedList<INode>();
		if (contents == null) {
			try {
				read();
			} catch (IOException e) {
				logger.error("Get child nodes error", e);
				return res;
			}
		}
		if (contents == null) {
			return res;
		}
		JSONArray ja = JSONArray.parseArray(contents);
		for (int i = 0; i < ja.size(); i++) {
			res.add(INode.fromJSON(ja.getJSONObject(i)));
		}
		return res;
	}

	public void write() throws IOException {
		if (file == null) {
			file = new File(GlobalConf.HASH_FOLDER + "/" + fileName);
		}
		if (file.exists())
			file.delete();
		BufferedWriter bw = new BufferedWriter(new FileWriter(file));
		bw.write(path + LINE_SEPARATOR + hash + LINE_SEPARATOR + contents);
		bw.close();
	}

	public void read() throws IOException {
		if (file == null)
			file = new File(GlobalConf.HASH_FOLDER + "/" + fileName);
		if (!file.exists()) {
			return;
		}
		BufferedReader br = new BufferedReader(new FileReader(file));
		path = br.readLine();
		hash = br.readLine();
		contents = br.readLine();
		br.close();
	}

	public String getHash() {
		return hash;
	}

	public String getPath() {
		return path;
	}

	public static boolean isExists(String path) {
		MessageDigest messageDigest = null;
		try {
			messageDigest = MessageDigest.getInstance("SHA-1");
		} catch (NoSuchAlgorithmException e) {
			// Will not happen.
		}
		messageDigest.reset();
		messageDigest.update(path.getBytes());
		byte[] bs = messageDigest.digest();
		String fileName = ByteUtil.bytesToString(bs);
		File file = new File(GlobalConf.HASH_FOLDER + "/" + fileName);
		return file.exists();
	}

	public void refresh() {
		try {
			new FileList().list(path);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}
		try {
			read();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}
